/*************************************************************
 *Name:           Christopher Alexander
 *Email address:  alexanc2@onid.oregonstate.edu
 *Class name:     CS362
 *Assignment:     Assignment #3
 *Description:    This file (cardtest2.c) contains unit tests
                  for village in dominion.c
 *************************************************************/

#include "dominion.h"
#include "dominion_helpers.h"
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <time.h>
#include "rngs.h"

#define NUM_UNIQUE_CARDS 27 //At least by my count this is right.
#define NUM_TESTS 5000

void fillWithCards(struct gameState *testState, int count, int flag, int *k, int player){

   int i;
   int randTreasure;
   int randKingdom;

   //Fill hand with random cards:
   if (flag == 0){
      for (i = 0; i < testState->handCount[player]; i++){
         if ( (rand() % 4) == 0){ //Add a treasure card 25% of the time.
            randTreasure = (rand() % 3); //33% of the time each for copper, silver, gold.
            if (randTreasure == 0) testState->hand[player][i] = copper;
            else if (randTreasure == 1) testState->hand[player][i] = silver;
            else testState->hand[player][i] = gold;
         }
         else { //Randomly fill with kingdom card 75% of the time.
            randKingdom = (rand() % 10); //There are 10 kingdom cards. Choose one randomly.
            if (randKingdom == 0) testState->hand[player][i] = k[randKingdom];
            else if (randKingdom == 1) testState->hand[player][i] = k[randKingdom];
            else if (randKingdom == 2) testState->hand[player][i] = k[randKingdom];
            else if (randKingdom == 3) testState->hand[player][i] = k[randKingdom];
            else if (randKingdom == 4) testState->hand[player][i] = k[randKingdom];
            else if (randKingdom == 5) testState->hand[player][i] = k[randKingdom];
            else if (randKingdom == 6) testState->hand[player][i] = k[randKingdom];
            else if (randKingdom == 7) testState->hand[player][i] = k[randKingdom];
            else if (randKingdom == 8) testState->hand[player][i] = k[randKingdom];
            else testState->hand[player][i] = k[randKingdom];
         }
      } //End fill hand with random cards.
   }
   else if (flag == 1){
      //Fill deck with random cards:
      for (i = 0; i < testState->deckCount[player]; i++){
          if ( (rand() % 4) == 0){ //Add a treasure card 25% of the time.
            randTreasure = (rand() % 3); //33% of the time each for copper, silver, gold.
            if (randTreasure == 0) testState->deck[player][i] = copper;
            else if (randTreasure == 1) testState->deck[player][i] = silver;
            else testState->deck[player][i] = gold;
         }
         else { //Randomly fill with kingdom card 75% of the time.
            randKingdom = (rand() % 10); //There are 10 kingdom cards. Choose one randomly.
            if (randKingdom == 0) testState->deck[player][i] = k[randKingdom];
            else if (randKingdom == 1) testState->deck[player][i] = k[randKingdom];
            else if (randKingdom == 2) testState->deck[player][i] = k[randKingdom];
            else if (randKingdom == 3) testState->deck[player][i] = k[randKingdom];
            else if (randKingdom == 4) testState->deck[player][i] = k[randKingdom];
            else if (randKingdom == 5) testState->deck[player][i] = k[randKingdom];
            else if (randKingdom == 6) testState->deck[player][i] = k[randKingdom];
            else if (randKingdom == 7) testState->deck[player][i] = k[randKingdom];
            else if (randKingdom == 8) testState->deck[player][i] = k[randKingdom];
            else testState->deck[player][i] = k[randKingdom];
         }
      } //End fill deck with random cards.
   }
   else {
      //Fill discard with random cards:
      for (i = 0; i < testState->discardCount[player]; i++){
          if ( (rand() % 4) == 0){ //Add a treasure card 25% of the time.
            randTreasure = (rand() % 3); //33% of the time each for copper, silver, gold.
            if (randTreasure == 0) testState->discard[player][i] = copper;
            else if (randTreasure == 1) testState->discard[player][i] = silver;
            else testState->discard[player][i] = gold;
         }
         else { //Randomly fill with kingdom card 75% of the time.
            randKingdom = (rand() % 10); //There are 10 kingdom cards. Choose one randomly.
            if (randKingdom == 0) testState->discard[player][i] = k[randKingdom];
            else if (randKingdom == 1) testState->discard[player][i] = k[randKingdom];
            else if (randKingdom == 2) testState->discard[player][i] = k[randKingdom];
            else if (randKingdom == 3) testState->discard[player][i] = k[randKingdom];
            else if (randKingdom == 4) testState->discard[player][i] = k[randKingdom];
            else if (randKingdom == 5) testState->discard[player][i] = k[randKingdom];
            else if (randKingdom == 6) testState->discard[player][i] = k[randKingdom];
            else if (randKingdom == 7) testState->discard[player][i] = k[randKingdom];
            else if (randKingdom == 8) testState->discard[player][i] = k[randKingdom];
            else testState->discard[player][i] = k[randKingdom];
         }
      } //End fill discard with random cards.
   }
}


int main() {
   int i, n;
   int seed = 1000;
   int numPlayers;
   int player;
   int bonus = 0;
   int choice1 = 0;
   int choice2 = 0;
   int choice3 = 0;
   int handPos = 0;
   int returnValue;
   int treasureCount;
   int bugA, bugB, bugC, bugD = 0;
   int k[10] = {adventurer, council_room, feast, gardens, mine,
               remodel, smithy, village, baron, great_hall};
   struct gameState testState;
   struct gameState preState;

   srand(time(NULL));
   printf("\nTesting adventurer card in cardEffect():\n");

   for (n = 0; n < NUM_TESTS; n++) {

      numPlayers = (rand() % 3) + 2; //There can be 2-4 players.

      initializeGame(numPlayers, k, seed, &testState); // initialize a new game

      player = rand() % numPlayers; //Randomly choose player to test.
      testState.whoseTurn = player;  //Make it this player's turn.

      testState.handCount[player] = (rand() % 10) + 1; //Player's hand size at start of turn. Have at least 1 card.
      testState.deckCount[player] = (rand() % 20); //How many cards are in player's deck
      testState.discardCount[player] = (rand() % 20); //How many cards are in player's discard pile.

      fillWithCards(&testState, testState.handCount[player], 0, k, player);
      fillWithCards(&testState, testState.deckCount[player], 1, k, player);
      fillWithCards(&testState, testState.discardCount[player], 2, k, player);

      handPos = rand() % testState.handCount[player]; //Card to play can be in any location in player's hand.
      testState.hand[player][handPos] = adventurer; //Make sure player has adventurer in hand at handPos position.

      memcpy(&preState, &testState, sizeof(struct gameState));

      //Counting the treasure cards in deck and discard for purpose of testing.
      for (i = 0; i < testState.deckCount[player]; i++){
         if (testState.deck[player][i] == copper || testState.hand[player][i] == silver || testState.deck[player][i] == gold){
            treasureCount++;
         }
      }
      for (i = 0; i < testState.discardCount[player]; i++){
         if (testState.discard[player][i] == copper || testState.discard[player][i] == silver || testState.discard[player][i] == gold){
            treasureCount++;
         }
      } //End treasure card counting.

      //Testing adventurer card.
      returnValue = cardEffect(testState.hand[player][handPos], choice1, choice2, choice3, &testState, handPos, &bonus);

      //Testing what cardEffect did.

      if (testState.handCount[player] < 0 && bugA == 0){
         printf("Bug found in adventurer card. (Test %d of %d)\n\thandCount of player is less than zero after calling function.\n", n, NUM_TESTS);
         bugA++;
      }

      if (treasureCount >= 2 && preState.handCount != testState.handCount -1 && bugB == 0){
         printf("Bug found in adventurer card. (Test %d of %d)\n"
                "\tThere were 2 treasure cards in deck + discard, but player's handCount is not 1 greater after calling function.\n"
                "\t(+ 2 for treasure cards, -1 for discard adventurer)\n", n, NUM_TESTS);
         bugB++;
      }

      //Note that this fault is not found due to the incorrect way in which the adventurer card is coded. Basically 2 wrongs made a right.
      if (treasureCount == 1 && preState.handCount != testState.handCount && bugC == 0){
         printf("Bug found in adventurer card. (Test %d of %d)\n"
                "\tThere was 1 treasure card in deck + discard, but player's handCount is not the same after calling function.\n"
                "\t(+ 1 for treasure cards, -1 for discard adventurer)\n", n, NUM_TESTS);
         bugC++;
      }

      if (treasureCount == 0 && preState.handCount != testState.handCount +1 && bugD == 0){
         printf("Bug found in adventurer card. (Test %d of %d)\n"
                "\tThere were 0 treasure cards in deck + discard, but player's handCount is not one less after calling function.\n"
                "\t(+ 0 for treasure cards, -1 for discard adventurer)\n", n, NUM_TESTS);
         bugD++;
      } //End Testing what cardEffect did.

      treasureCount = 0; //Reset for next test run.
   }

   return 0;
}
